package com.antler.mobilesniffer;

import android.app.Service;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.provider.ContactsContract;

import com.antler.utils.MyLog;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class MainService extends Service {
    protected static final String TAG = "[ANTLER]" + MainService.class.getSimpleName();

    public static final String ACTION_FORWARD_SMS = "mobilesniffer.intent.action.FORWARD_SMS";
    public static final String ACTION_FORWARD_CALL = "mobilesniffer.intent.action.FORWARD_CALL";

    public static final String SMS_RECEIVE_TIME = "sms_receive_time";
    public static final String SMS_NUMBER = "sms_number";
    public static final String SMS_BODY = "sms_body";

    public static final String CALL_RECEIVE_TIME = "call_receive_time";
    public static final String CALL_NUMBER = "call_number";

    protected static final String SERVER_BASE_URL = "http://192.168.31.130:1109";
    protected static final String API_FORWARD_SMS = "/api/forward_sms";
    protected static final String API_FORWARD_CALL = "/api/forward_call";

    protected final OkHttpClient mOkHttpClient = new OkHttpClient();

    private final Uri SMS_INBOX = Uri.parse("content://sms/inbox");

    protected SmsObserver mSmsObserver;

    class SmsObserver extends ContentObserver {
        public SmsObserver(Context context, Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);

            getSmsFromPhone();
        }
    }

    public MainService() {
        MyLog.log(TAG, "MainService");
    }

    @Override
    public void onCreate() {
        MyLog.log(TAG, "onCreate");
        super.onCreate();

        mSmsObserver = new SmsObserver(this, null);
        getContentResolver().registerContentObserver(SMS_INBOX, true, mSmsObserver);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        MyLog.log(TAG, "onStartCommand: " + intent);

        if (null != intent) {
            String action = intent.getAction();
            if (null != action) {
                if (action.equals(ACTION_FORWARD_SMS)) {
                    String receiveTime = intent.getStringExtra(MainService.SMS_RECEIVE_TIME);
                    String senderNumber = intent.getStringExtra(MainService.SMS_NUMBER);
                    String sender = getContactNameFromPhoneBook(this, senderNumber);
                    String body = intent.getStringExtra(MainService.SMS_BODY);

                    MyLog.log(TAG, String.format("time:%s, senderNumber:%s, sender:%s, body:%s", receiveTime, senderNumber, sender, body));

                    doSendSMS(receiveTime, senderNumber, sender, body);
                } else if (action.equals(ACTION_FORWARD_CALL)) {
                    String receiveTime = intent.getStringExtra(MainService.CALL_RECEIVE_TIME);
                    String callerNumber = intent.getStringExtra(MainService.CALL_NUMBER);
                    String caller = getContactNameFromPhoneBook(this, callerNumber);

                    MyLog.log(TAG, String.format("time:%s, callerNumber:%s, caller:%s", receiveTime, callerNumber, caller));

                    doSendCall(receiveTime, callerNumber, caller);
                }
            }
        }

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        MyLog.log(TAG, "onDestroy");
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    protected void doSendSMS(String time, String senderNumber, String sender, String body) {
        final String requestUrl = SERVER_BASE_URL + API_FORWARD_SMS;

        RequestBody formBody = new FormBody.Builder()
                .add("time", time)
                .add("senderNumber", senderNumber)
                .add("sender", sender)
                .addEncoded("body", body)
                .build();

        Request request = new Request.Builder()
                .url(requestUrl)
                .post(formBody)
                .build();

        Call call = mOkHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                MyLog.log(TAG, "doSendSMS onFailure exception: " + e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String str = response.body().string();

                MyLog.log(TAG, "doSendSMS onResponse body: " + str);
            }
        });
    }

    protected void doSendCall(String time, String callerNumber, String caller) {
        final String requestUrl = SERVER_BASE_URL + API_FORWARD_CALL;

        RequestBody formBody = new FormBody.Builder()
                .add("time", time)
                .add("callerNumber", callerNumber)
                .add("caller", caller)
                .build();

        Request request = new Request.Builder()
                .url(requestUrl)
                .post(formBody)
                .build();

        Call call = mOkHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                MyLog.log(TAG, "doSendCall onFailure exception: " + e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String str = response.body().string();

                MyLog.log(TAG, "doSendCall onResponse body: " + str);
            }
        });
    }

    protected String getContactNameFromPhoneBook(Context context, String phoneNum) {
        String contactName = "";

        try {
            if (phoneNum.startsWith("+") && phoneNum.length() > 11) {
                phoneNum = phoneNum.substring(phoneNum.length() - 11);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        ContentResolver cr = context.getContentResolver();
        Cursor pCur = cr.query(
                ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                ContactsContract.CommonDataKinds.Phone.NUMBER + " = ?",
                new String[]{phoneNum}, null);

        if (pCur.moveToFirst()) {
            contactName = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            pCur.close();
        }
        return contactName;
    }

    public void getSmsFromPhone() {
        try {
            ContentResolver cr = getContentResolver();
            String[] projection = new String[]{"_id", "read", "address", "date", "body"};
            Cursor cur = cr.query(SMS_INBOX, projection, null, null, "date desc");
            if (null == cur) {
                MyLog.log(TAG, "getSmsFromPhone query null");
                return;
            }

            SimpleDateFormat dataFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            while (cur.moveToNext()) {
                int _id = cur.getInt(0);
                int read = cur.getInt(1);
                String address = cur.getString(2);
                long millisTime = Long.parseLong(cur.getString(3));
                Date date = new Date(millisTime);
                String body = cur.getString(4);

                long now = System.currentTimeMillis();
                if (now - millisTime <= TimeUnit.MINUTES.toMillis(1) /*&& read == 0*/) {

                    String receiveTime = dataFormat.format(date);

                    MyLog.log(TAG, String.format("time:%s, number:%s, body:%s", receiveTime, address, body));

                    Intent intentSMSMsg = new Intent(this, MainService.class);
                    intentSMSMsg.setAction(MainService.ACTION_FORWARD_SMS);
                    intentSMSMsg.putExtra(MainService.SMS_RECEIVE_TIME, receiveTime);
                    intentSMSMsg.putExtra(MainService.SMS_NUMBER, address);
                    intentSMSMsg.putExtra(MainService.SMS_BODY, body);
//                    startService(intentSMSMsg);
                }
            }

            cur.close();

//            ContentValues cv = new ContentValues();
//            cv.put("read", 1);
//            cr.update(SMS_INBOX, cv, null, null);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
